package com.smartlock;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.smartlock.service.BindLockService;
import com.smartlock.service.HeatBeatService;
import com.smartlock.service.RemoteUnLockService;
import com.smartlock.service.UnLockService;
import com.smartlock.util.BytesUtils;

/**
 * Created by dhl on 2017/12/20.
 */
public class LockTask implements Runnable {

    private Logger           logger = LoggerFactory.getLogger(LockTask.class);
    private SimpleDateFormat sdf    = new SimpleDateFormat("yyyyMMddhhmmss");
    private String           address;
    private Socket           socket;
    private InputStream      in;
    private OutputStream     out;
    private String           gatewayMac;
    private long             threadId;

    public LockTask(Socket socket) {
        this.socket = socket;
        this.address = socket.getInetAddress().getHostAddress();
    }

    @Override
    public void run() {
        try {
            threadId = Thread.currentThread().getId();
            System.out.println("create thread" + threadId);
            in = socket.getInputStream();
            out = socket.getOutputStream();
            while (true) {
                long start = System.currentTimeMillis();
                byte[] b = new byte[32];
                in.read(b);
                String serviceCode = String.format("%02X", b[7]);
                logger.info("接收到锁客户端请求信息，网关Mac=" + gatewayMac + ",serviceCode=" + serviceCode + ",请求指令为："
                            + BytesUtils.formatHexString(b));
                byte[] returnMsg;
                if ("00".equalsIgnoreCase(serviceCode)) {
                    byte[] gatewayMacBytes = new byte[6];
                    System.arraycopy(b, 8, gatewayMacBytes, 0, 6);
                    gatewayMac = BytesUtils.formatHexString(gatewayMacBytes);
                    returnMsg = HeatBeatService.heatbeatHandle(b, socket, gatewayMac);
                } else if ("20".equalsIgnoreCase(serviceCode)) {
                    returnMsg = BindLockService.bindLock(b, gatewayMac);
                    if (returnMsg == null) { //app绑定失败，或者app绑定验证请求超时
                        logger.info(
                            "app绑定失败，忽略本条绑定指令，不做响应。gateMac=" + gatewayMac + ",绑定指令为：" + BytesUtils.formatHexString(b));
                        continue;
                    }
                } else if ("05".equalsIgnoreCase(serviceCode)) {
                    returnMsg = UnLockService.unlockPush(b);
                } else if ("01".equals(serviceCode)) {
                    String remoteUnLockResult = String.format("%02X", b[16]);
                    String remoteOpenLockCommand = RemoteUnLockService.getRemoteUnLockTask(gatewayMac);
                    if ("00".equals(remoteUnLockResult)) {
                        logger.info("远程开锁成功！网关MAC=" + gatewayMac + ",command=" + remoteOpenLockCommand + ",result="
                                    + BytesUtils.formatHexString(b));

                    } else {
                        logger.error("远程开锁失败！网关MAC=" + gatewayMac + ",command=" + remoteOpenLockCommand + ",result="
                                     + BytesUtils.formatHexString(b));
                    }
                    RemoteUnLockService.pushLockMsgToBackground(b, gatewayMac, remoteUnLockResult);
                    continue;
                } else {
                    logger.error("不能处理这种服务码的业务：" + serviceCode);
                    continue;
                }
                out.write(returnMsg);
                out.flush();
                long end = System.currentTimeMillis();
                printBytes(b, returnMsg);
                logger.info(threadId + "*****" + serviceCode + "*****" + sdf.format(new Date())
                            + "req is end---use time :" + (end - start));
                System.out.println(threadId + "*****" + serviceCode + "*****" + sdf.format(new Date())
                                   + "req is end---use time :" + (end - start));

            }
        } catch (SocketTimeoutException e) {
            logger.error("socket超时没有反馈，认为锁客户端socket已断开，终止线程。", e);
        } catch (IOException e) {
            logger.error("socketIO异常，终止线程。", e);
        } catch (InterruptedException e) {
            logger.error("socketIO异常，终止线程。", e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
                if (socket != null) {
                    socket.close();
                    System.out.println(threadId + "socket closed");
                }
                RemoteUnLockService.getRemoteUnLockTask(gatewayMac);
                Main.getMacSocketMap().remove(gatewayMac);
            } catch (Exception ex) {
                logger.error("关闭socket线程时，抛出异常：", ex);
            }
        }
    }

    private void printBytes(byte[] paramMsg, byte[] returnMsg) {
        System.out.println(threadId + "accept req -----------ip = " + address);

        System.out.println(threadId + "param :");
        System.out.println(BytesUtils.formatBytesString(paramMsg));
        System.out.println();

        System.out.println(BytesUtils.formatHexString(paramMsg));
        System.out.println();

        System.out.println(threadId + "return :");
        System.out.println(BytesUtils.formatBytesString(returnMsg));
        System.out.println();

        System.out.println(BytesUtils.formatHexString(returnMsg));
        System.out.println();
    }

}
